One of the most common questions is "how can I print / print preview my form"? This is quite easily done by getting the form to "draw itself" on the printed page but this is often unsatisfactory because:
The attached component addresses the problem in a different manner.... What you do is drop a FormPrintHelperComponent component onto your form an it extends each control with a bunch of new properties (look in the properties window for each control in the section named "MCL Form Print Helper").
You then set these to indicate:
Print - Whether or not the control should be printedPrintMethod - Whether to print it as Text, Image or using an Owner Drawn functionBoundingRectangle - The boundary rectangle to print it in (measured in printer units)LeftBorder, RightBorder, TopBorder, BottomBorder - The pens to use (if any) to draw a border around the bounding rectangleBackColour - The colour to fill the bounding rectangle withThe component then allows you to preview the printed page at design time and to preview or print it at run time
The component implements System.ComponentModel.IExtenderProvider which means it provides properties to the other controls on the form -
in the same way as the built in ToolTip and F1 Help provider components do.
The class is decorated with ProvideProperty attributes which tells the IDE which properties the control provides to extend the
properties of the controls on the form. Underlying each of these "properties" are a matched pair of a function and sub routine to get/set the property
for the control passed in which are called if an extended property is changed in the target control's property window.
<ProvideProperty("Print", GetType(System.Windows.Forms.Control))> _
Public Class FormPrintHelperComponent
Implements System.ComponentModel.IExtenderProvider
'- - 8< - - - - - - - - - - - - - - - - -
#Region "Print"
''' <summary>
''' True to include this control on the printed page
''' </summary>
''' <param name="myControl">The control being extended</param>
''' <returns></returns>
''' <remarks></remarks>
<Category("MCL Form Print Utility"), Description("True to include this control on the printed page")> _
Public Function GetPrint(ByVal myControl As Control) As Boolean
If TypeOf (myControl) Is Form Then
'\\ Forms print by default..
Return True
Else
Return _ControlSettings.Item(myControl).Print
End If
End Function
''' <summary>
''' True to include this control on the printed page
''' </summary>
''' <param name="myControl">The control being extended</param>
''' <param name="Value">Whether or not to print this item</param>
''' <remarks></remarks>
<Category("MCL Form Print Utility"), Description("True to include this control on the printed page")> _
Public Sub SetPrint(ByVal myControl As Control, ByVal Value As Boolean)
_ControlSettings.Item(myControl).Print = Value
End Sub
#End Region
'- - 8< - - - - - - - - - - - - - - - - -
End Class
When the component is invoked to print or print preview, it iterates through all the controls on the form that have the extended property Print set to true. It then prints the control according to the other extended properties provided for that control such as boundary
rectangle, font, foreground and background colour etc.
The PrintMode extended property affects how the control is printed. There are three options:-
PrintAsText - Prints the "Text" property of the controlPrintAsImage - Prints the "Image" property of the control if it has one, or otherwise prints the control as a bitmap exactly as it appears on screenPrintAsOwnerDrawn - Passes the control to the OwnerDrawnControlprint event so the application can decide how to print the controlWhen the print mode is PrintAsText the control is printed using the following properties:
ForeColour - The foreground colour to print the text inPropertyToPrint - specifies which property of the control to get the text from. This defaults to "Text" but can be changed to any property that the control class exposes. (Note that setting this property is case-sensitive)PrintFont - specifies the font (size and style) to use to print the control text. This allows you to use a different font for the on screen and on paper representations of the controlTrimming - specifies how to format the text if it overflows the available space set in the BoundingRectangle propertyIf the control doesn't have an Image attribute the control is drawn onto a bitmap which is then printed on the form by using the control class' DrawToBitmap method:
Private Function GetControlImage(ByVal ctlIn As Control) As Image
Dim Imageproperty As System.Reflection.PropertyInfo
Imageproperty = ctlIn.GetType.GetProperty("Image", GetType(Image))
If Imageproperty Is Nothing Then
Dim imgNew As New Bitmap(ctlIn.Width, ctlIn.Height)
ctlIn.DrawToBitmap(imgNew, ctlIn.ClientRectangle)
Return imgNew
Else
Return CType(Imageproperty.GetValue(ctlIn, Nothing), Image)
End If
End Function
If you set the extended property PrintMode to PrintAsOwnerDrawn then at run time when the print or print preview logic is invoked an OwnerDrawnControlPrint event will be raised to allow you to programatically draw the control onto the page canvas.
Private Sub FormPrintHelperComponent1_OwnerDrawnControlPrint(ByVal sender As Object, ByVal e As MCL_Form_Print_Control.OwnerPrintControlEventArgs) Handles FormPrintHelperComponent1.OwnerDrawnControlPrint
'\\ The application code should draw this control because it is special....
With e
If .ControlToPrint.Name = "DateTimePicker1" Then
e.Canvas.FillRectangle(Brushes.Aqua, e.BoundingRectangle)
e.Canvas.DrawString(">> " & .ControlToPrint.Text & "<<", .ControlToPrint.Font, Brushes.Azure, e.BoundingRectangle)
End If
End With
End Sub
Of course there are many cases where a single form needs to be printed over multiple logical pages - for example if a form has many tabs on it you might find it sensible to print one logical page per tab
The component implements this functionality by having a property LogicalPages which is a positive number 1 or greater that is the number of logical pages that this form should be printed over. Then for each control two additional extended properties are added that control which pages that control is to be printed on: MultiPageprintMethod which is an enumerated type:
PrintOnEveryPage - Print the control on every logical pagePrintOnOddPages - Print the control on odd numbered logical pagesPrintOnEvenPages - Print the control on even numbered logical pagesPrintOnlyOnSpecifiedLogicalPages - Print the control only on the specified pagesPrintOnlyOnSpecifiedLogicalPages then a second extended property, PrintOnPages (which is a list of boolean values, one for each logical page) is used to set the page(s) to print it on
When the data in a control (such as a multi-line textbox, a rich textbox or a grid) is too large for the area allocated to print it on the document you can optionally set it to flow over to a new page until it reaches the end of the data by setting the extended property DataOverflowAction to CreateNewPage. However the new page will be the same logical page as the current one (with all the same controls on it) but will be a different physical page. The use of logical pages at the design stage allows a multi part document to be created that does not need to change at run time to accomodate extra data.
When the control extends a RichTextBox control it adds a further extended property to that control, RichTextBoxPrintMethod which is an enumerated type that is used to set whether the text box contents should be printed as plain text or as formatted rich text.
PlainText - Print just the text of the control, using the printFont and related propertiesRichText - Print the formatted rich text of the control, ignoring the printFont and related propertiesWhen the control extends a DataGrid or DataGridView control it adds a further extended property to that control, CellFormats which is a collection of formats describing how each cell in that grid should be printed.